package ClientCont ;

import ocsf.client.*;

import java.io.*;


public class ChatClient extends ObservableSWRClient
{
	
	/** The wait_retries. */
	private int wait_retries = 0;
	
	/** The max_retries. */
	private int max_retries = 2;
	
	/** The recieved_obj. */
	public Object recieved_obj=null;
  //Instance variables **********************************************
  
  /**
   * The interface type variable.  It allows the implementation of 
   * the display method in the client.
   */
  //ChatIF	 clientUI; 

  
  //Constructors ****************************************************
  
  /**
   * Constructs an instance of the chat client.
   *
   * @param host The server to connect to.
   * @param port The port number to connect on.
   * @param clientUI The interface type variable.
   */
	public ChatClient() 
	{
		super("127.0.0.1", 0); //Call the superclass constructor
	}	 
	
	
	/**
	 * Start a new connection to the server.
	 *
	 * @param host The host to connect to.
	 * @param port  The port to connect to.
	 * @throws IOException Signals that an I/O exception has occurred.
	 */	
	public void startConnection(String host, int port) throws IOException
	{
		setHost(host);
		setPort(port);
		openConnection();
	}
	
	/**
	 * Instantiates a new chat client.
	 *
	 * @param host the host
	 * @param port the port
	 */
	public ChatClient(String host, int port) 
	{
		super(host, port); //Call the superclass constructor
    }
	
	  //Instance methods ************************************************
    
  /**
   * This method handles all data that comes in from the server.
   *
   * @param msg The message from the server.
   */
  public void handleMessageFromServer(Object msg) 
  {
    //clientUI.display(msg.toString());
	//Class msg_cls = msg.getClass();  
	System.out.println("The type of the object is: " + msg.toString());  
    System.out.println("ChatClient: recived from server msg type = " + msg.getClass().toString());
    
    recieved_obj = msg;
   /* switch (msg.getClass().toString())
    {
    
 
    }*/
    
  	setChanged(); //Marks this Observable object as having been changed
  	notifyAll();  //Wakes up all threads that are waiting on this object's monitor
  	
  }

  /**
   * This method handles all data coming from the UI.
   *
   * @param message The message from the UI.
   * @throws IOException Signals that an I/O exception has occurred.
   */
  public void handleMessageFromClientUI(Object message)  throws IOException
  {
	  sendToServer(message);
  }
  
  /**
   * This method terminates the client.
   */
  public void quit()
  {
    try
    {
      closeConnection();
    }
    catch(IOException e) {}
  //  System.exit(0);
  }



	/**
	 * Sets how many retries to wait.
	 *
	 * @param wt number of wait for retries
	 */
	public void setWaitRetries(int wt)
	{
		this.wait_retries = wt;
	}
	
	/**
	 * get the number of wait retries.
	 * @return wait retries set to this client.
	 */
	public int getWaitRetries()
	{
		return this.wait_retries;
	}
	
	/**
	 * Sets the max retries to this client.
	 * @param mr	max retries.
	 */
	public void setMaxRetries(int mr)
	{
		this.max_retries = mr;
	}
	
	/**
	 * Get the max retries number.
	 * @return max retries number.
	 */	
	public int getMaxRetries()
	{
		return this.max_retries;
	}
	
	/**
	 * Sends a message to the server and waits for a specific response or timeout.
	 *
	 * @param message The message to be sent to the server
	 * @param expected_obj The type of message expected to be received from the server.
	 * @return The result message from the server.
	 */
	public synchronized Object sendToServerAndWait(Object message,Object expected_obj)
	{
		wait_retries=0;
		recieved_obj=null;
		
		clearAll();
		try 
		{
			System.out.println("ChatClient > sending to server MSG : "+ message.toString() );
			sendToServer(message);
		}
		catch (IOException e1) 
		{
			
			System.out.println("ChatClient: IOException!");
			return null;
		}

		while(true)
		{
			try
			{
				if ((recieved_obj != null) && (recieved_obj.getClass() == expected_obj.getClass()))
				{	
					return recieved_obj;
				}
				
				if (isCancelled()) 
				{
					System.out.println("ChatClient: CANCELED!");	
					return null;
				}
				System.out.println("ChatClient: waiting..");
				wait(6000);
				wait_retries++;
				// send Waiting to observers.
				setChanged(); //Marks this Observable object as having been changed
				notifyObservers(WAITING_FOR_REPLY);// notify all of its observers ,
				// Each observer has its update method called with two arguments: this observable object and the arg argument.
			}
			catch (InterruptedException e) 
			{
				//
				System.out.println("ChatClient: InterruptedException!");
				return null;
			}
			catch (IllegalMonitorStateException e)
			{
				//
				System.out.println("ChatClient: IllegalMonitorStateException!");
				return null;
			}
			catch (NullPointerException e)
			{
				System.out.println("ChatClient: NullPointerException!");
				return null;
			}
		}
	}
}

//End of ChatClient class
